﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LiteExpress.Utilities
{
    public class PagerModel
    {
        #region private
        private int _pageCount;
        private int _minPage;
        private int _maxPage;
        private string _linkFormat;
        #endregion

        #region public
        public string pageParmName = "page";
        public int ItemCount = 0;
        public int PageSize = 10;
        public int IntervalLength = 2;
        public int StartIndex = 1;
        #endregion

        #region helper
        public int CurrentIndex
        {
            get
            {
                return int.Parse(System.Web.HttpContext.Current.Request[pageParmName] ?? StartIndex.ToString());
            }
        }

        public int PageCount
        {
            get
            {
                if (ItemCount % PageSize == 0)
                {
                    _pageCount = (int)ItemCount / PageSize;
                }
                else
                {
                    _pageCount = (int)ItemCount / PageSize + 1;
                }
                return _pageCount;
            }
        }

        private string LinkFormat
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_linkFormat))
                {

                    var querys = System.Web.HttpUtility.ParseQueryString(System.Web.HttpContext.Current.Request.Url.Query);
                    if (querys[pageParmName] != null)
                    {
                        querys.Remove(pageParmName);
                    }

                    StringBuilder pathsb = new StringBuilder();
                    pathsb.Append(System.Web.HttpContext.Current.Request.Url.AbsolutePath);
                    //result += "?" + pageParmName + "={0}";
                    for (int i = 0; i < querys.Count; i++)
                    {
                        if (i == 0)
                        {
                            pathsb.Append("?");
                        }
                        else
                        {
                            pathsb.Append("&");
                        }
                        pathsb.AppendFormat("{0}={1}", querys.Keys[i], System.Web.HttpUtility.UrlEncode(querys[i]));
                    }

                    if (querys.Count > 0)
                    {
                        pathsb.AppendFormat("&{0}=", pageParmName);
                    }
                    else
                    {
                        pathsb.AppendFormat("?{0}=", pageParmName);
                    }

                    _linkFormat = pathsb.ToString();
                }
                return _linkFormat;
            }
        }

        private int MinPage
        {
            get
            {
                _minPage = System.Math.Max(StartIndex, CurrentIndex - IntervalLength);
                if (PageCount - IntervalLength < CurrentIndex - StartIndex + 1 && CurrentIndex - StartIndex + 1 <= PageCount)
                {
                    _minPage = System.Math.Max(StartIndex, PageCount - 2 * IntervalLength + StartIndex - 1);
                }
                return _minPage;
            }
        }

        private int MaxPage
        {
            get
            {
                _maxPage = System.Math.Min(PageCount + StartIndex - 1, CurrentIndex + IntervalLength);
                if (0 <= CurrentIndex - StartIndex && CurrentIndex - StartIndex < IntervalLength)
                {
                    _maxPage = System.Math.Min(PageCount + StartIndex - 1, 2 * IntervalLength + StartIndex);
                }

                if (_maxPage < StartIndex)
                {
                    _maxPage = StartIndex;
                }
                return _maxPage;
            }
        }

        public int DisplayCurrentIndex
        {
            get
            {
                return CurrentIndex - StartIndex + 1;
            }
        }
        public int DisplayFromIndex
        {
            get
            {
                return Math.Min((this.CurrentIndex - this.StartIndex) * this.PageSize + 1, this.ItemCount);
            }
        }

        public int DisplayToIndex
        {
            get
            {
                return Math.Min(this.ItemCount, (this.CurrentIndex - this.StartIndex + 1) * this.PageSize);
            }
        }

        public PagerLink FirstPageLink
        {
            get
            {
                return new PagerLink
                {
                    Number = 1
                    , Url = (this.LinkFormat + this.StartIndex.ToString())
                    , IsValid = (this.CurrentIndex > this.StartIndex && this.MinPage > this.StartIndex)
                };
            }
        }

        public PagerLink PreviousPageLink
        {
            get
            {
                return new PagerLink
                {
                    Number = (this.CurrentIndex - this.StartIndex)
                    , Url = (this.LinkFormat + (this.CurrentIndex - 1).ToString())
                    , IsValid = (this.CurrentIndex > this.StartIndex)
                };
            }
        }

        public PagerLink NextPageLink
        {
            get
            {
                return new PagerLink
                {
                    Number = (this.CurrentIndex - this.StartIndex + 2)
                    , Url = (this.LinkFormat + (this.CurrentIndex + 1).ToString())
                    , IsValid = (this.CurrentIndex - this.StartIndex + 1 < this.PageCount)
                };
            }
        }

        public PagerLink LastPageLink
        {
            get
            {
                return new PagerLink
                {
                    Number = this.PageCount
                    , Url = (this.LinkFormat + (this.PageCount + this.StartIndex - 1).ToString())
                    , IsValid = (this.CurrentIndex - this.StartIndex + 1 < this.PageCount && this.MaxPage < this.PageCount + this.StartIndex - 1)
                };
            }
        }

        public IEnumerable<PagerLink> PageLinks
        {
            get
            {
                for (int i = this.MinPage; i <= this.MaxPage; i++)
                {
                    yield return new PagerLink
                    {
                        Number = (i - this.StartIndex + 1)
                        , Url = (this.LinkFormat + i.ToString())
                        , IsValid = this.CurrentIndex != i
                    };
                }
            }
        }

        #endregion

        public class PagerLink
        {
            public bool IsValid { get; set; }
            public int Number { get; set; }
            public string Url { get; set; }
        }
    }
}
